using System;
using DG.Tweening;
using Minesweeper.Campsite;
using UnityEngine;
using static Minesweeper.GameStatic;

namespace Minesweeper
{
    [RequireComponent(typeof(SpriteRenderer))]
    public class CampsitePlayer : MonoBehaviour
    {
        public static CampsitePlayer Instance;

        public float movementSpeed = 1 / 0.15f; // 扫雷模式的玩家就是间隔0.15秒移动一格
    
        public Sprite right, up, down;

        public new Camera camera;
        public float scrollSensitivity = 1;
        public float minSize = 1, maxSize = 10;
        public float cursorFollowSensitivity = 0.25f;
        public float followSpeed = 4;
        public Transform shovel;

        public Seat SittingObject { get; set; }

        public SpriteRenderer SpriteRenderer => GetComponent<SpriteRenderer>();

        private float _curSize;

        private Rigidbody2D Rigidbody => GetComponent<Rigidbody2D>();
        
        private void Awake()
        {
            Instance = this;
            _curSize = (minSize + maxSize) / 2;
            camera.orthographicSize = _curSize;
        }

        private bool _mirrored;

        private Vector3Int _snappingPos;
        private Tween _snappingTween;

        private Vector2 _positionBeforeSitting;

        public void SetMirrored(bool mirrored)
        {
            _mirrored = mirrored;
            if (_mirrored)
                transform.DOScaleX(-1, .1f).SetEase(Ease.OutSine);
            else
                transform.DOScaleX(1, .1f).SetEase(Ease.OutSine);
        }
        
        public void Sit(Seat seat, Vector2 offset)
        {
            _positionBeforeSitting = transform.position;
            transform.position = seat.transform.position + (Vector3)offset;
            SittingObject = seat;
            if (SittingObject.TryGetComponent(out SpriteRenderer r))
                r.sortingOrder = SpriteRenderer.sortingOrder - 1;
            Rigidbody.simulated = false;
        }
        
        private void Update()
        {
            if (Paused)
                return;
            
            var movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));

            if (movement != Vector2.zero)
            {
                if (SittingObject)
                {
                    if (SittingObject.TryGetComponent(out SpriteRenderer r))
                        r.sortingOrder = SpriteRenderer.sortingOrder;
                    SittingObject = null;
                    transform.position = _positionBeforeSitting;
                    Rigidbody.simulated = true;
                }
                movement = movementSpeed * movement.normalized;
                Rigidbody.velocity = movement;

                var angle = Mathf.Atan2(movement.y, movement.x) * Mathf.Rad2Deg;

                switch (angle)
                {
                    case > -45 and < 45:
                    {
                        if (SpriteRenderer.sprite != right)
                            SpriteRenderer.sprite = right;
                        if (_mirrored)
                        {
                            _mirrored = false;
                            transform.DOScaleX(1, .1f).SetEase(Ease.OutSine);
                        }

                        break;
                    }
                    case > 45 and < 135:
                    {
                        if (SpriteRenderer.sprite != up)
                            SpriteRenderer.sprite = up;
                        
                        break;
                    }
                    case > 135 or < -135:
                    {
                        if (SpriteRenderer.sprite != right)
                            SpriteRenderer.sprite = right;
                        if (!_mirrored)
                        {
                            _mirrored = true;
                            transform.DOScaleX(-1, .1f).SetEase(Ease.OutSine);
                        }

                        break;
                    }
                    case > -135 and < -45:
                    {
                        if (SpriteRenderer.sprite != down)
                            SpriteRenderer.sprite = down;
                        
                        break;
                    }
                }
                _snappingTween.Kill();
            }
            else
            {
                Rigidbody.velocity = Vector2.zero;
                if (Input.GetKeyDown(KeyCode.LeftShift))
                {
                    if (transform.position != _snappingPos)
                    {
                        _snappingPos = Vector3Int.RoundToInt(transform.position);
                        _snappingTween = transform.DOMove(_snappingPos, .5f).SetEase(Ease.OutCubic);
                    }
                }
                if (Input.GetKeyUp(KeyCode.LeftShift) && _snappingTween is { active: true })
                    _snappingTween.Kill();
            }

            var scrollDelta = Input.mouseScrollDelta.y;
            if (scrollDelta != 0)
            {
                _curSize -= scrollDelta * scrollSensitivity;
                if (_curSize < minSize)
                    _curSize = minSize;
                if (_curSize > maxSize)
                    _curSize = maxSize;
                camera.DOOrthoSize(_curSize, 0.5f).SetEase(Ease.OutSine);
            }

            Vector2 p = Input.mousePosition;
            var sr = camera.pixelWidth / camera.pixelHeight;
            var hr = 2 * p.x / camera.pixelWidth - 1;
            var vr = 2 * p.y / camera.pixelHeight - 1;
            var ov = (Vector2)transform.position + new Vector2(
                hr * cursorFollowSensitivity * camera.orthographicSize * sr,
                vr * cursorFollowSensitivity * camera.orthographicSize);

            if ((Vector2)camera.transform.position != ov)
            {
                var camPos = Vector2.Lerp(camera.transform.position, ov, followSpeed * Time.deltaTime);
                camera.transform.position = new Vector3(camPos.x, camPos.y, -10);
            }
            else
            {
                camera.transform.position = new Vector3(ov.x, ov.y, -10);
            }
        }
    }
}
